﻿using HDSmartCommunity.BUS;
using HDSmartCommunity.DAL;
using HDSmartCommunity.Models;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace HDSmartCommunity.DevicePlatform
{
    public class RaspberryPie
    {
        public bool SetNtp(string ipAddress)
        {
            try
            {
                RunCommand("chmod 777 /etc/ntp.conf");
                using (FileStream fs = new FileStream("/etc/ntp.conf", FileMode.Open, FileAccess.Write))
                {
                    StreamWriter sw = new StreamWriter(fs);
                    sw.BaseStream.Seek(0, SeekOrigin.Current);
                    sw.WriteLine(string.Format("server {0} prefer", ipAddress));
                    sw.Flush();
                    sw.Close();
                    fs.Close();
                }
                DeviceDAL da = new DeviceDAL();
                da.UpdatNtpServer(ipAddress);

                //RunCommand("reboot");
                return true;
            }
            catch (Exception e)
            {
                LogHelper.Log(e.ToString());
                return false;
            }
        }

        public void RunCommand(string command)
        {
            Process.Start("sudo", command);
        }

        public NetInfo GetNetInfo()
        {
            NetInfo netInfo = new NetInfo();
            StreamReader reader = new StreamReader(@"/etc/dhcpcd.conf", Encoding.Default);
            string theReply = reader.ReadToEnd();
            reader.Close();
            Regex addressRegex = new Regex(@"(?<ip>([^\w\s]+|\s*)static\s*ip_address=\d+.\d+.\d+.\d+/\d+)\s*");
            Regex routerRegex = new Regex(@"(?<router>([^\w\s]+|\s*)static\s*routers=\d+.\d+.\d+.\d+)\s*");
            Regex serverRegex = new Regex(@"(?<server>([^\w\s]+|\s*)static\s*domain_name_servers=\d+.\d+.\d+.\d+)\s*");
            Regex ipRegex = new Regex(@"=\s*(?<ip>\d+.\d+.\d+.\d+)\s*");
            Regex maskReg = new Regex(@"=\s*\d+.\d+.\d+.\d+/(?<mask>\d+)\s*");

            MatchCollection addressCollection = addressRegex.Matches(theReply);
            MatchCollection routerCollection = routerRegex.Matches(theReply);
            MatchCollection serverCollection = serverRegex.Matches(theReply);

            for (int i = 0; i < addressCollection.Count; i++)
            {
                string str = addressCollection[i].Groups["ip"].Value.Trim();
                if (!str.Contains("#"))
                {
                    string ip = ipRegex.Matches(str)[0].Groups["ip"].Value.Trim();
                    netInfo.IP = ip;
                    int mask = Convert.ToInt32(maskReg.Matches(str)[0].Groups["mask"].Value.Trim());
                    netInfo.Mask = GetMask(mask);
                }
            }

            for (int i = 0; i < routerCollection.Count; i++)
            {
                string str = routerCollection[i].Groups["router"].Value.Trim();
                if (!str.Contains("#"))
                {
                    string ip = ipRegex.Matches(str)[0].Groups["ip"].Value.Trim();
                    netInfo.Router = ip;
                }
            }

            for (int i = 0; i < serverCollection.Count; i++)
            {
                string str = serverCollection[i].Groups["server"].Value.Trim();
                if (!str.Contains("#"))
                {
                    string ip = ipRegex.Matches(str)[0].Groups["ip"].Value.Trim();
                    netInfo.Server = ip;
                }
            }

            return netInfo;
        }

        public NetInfo GetJMNetInfo1()
        {
            NetInfo netInfo = new NetInfo();
            try
            {
                StreamReader reader = new StreamReader(@"/etc/network/interfaces", Encoding.Default);
                string theReply = reader.ReadToEnd();
                reader.Close();
                Regex strRegex = new Regex(@"(?<str>([^\w\s]+|\s*)auto\s*enp1s0\s*iface\s*enp1s0\s*inet\s*static)");
                Regex addressRegex = new Regex(@"(?<address>([^\w\s]+|\s*)address\s*\d+.\d+.\d+.\d+)\s*");
                Regex gatewayRegex = new Regex(@"(?<gateway>([^\w\s]+|\s*)gateway\s*\d+.\d+.\d+.\d+)\s*");
                Regex maskRegex = new Regex(@"(?<netmask>([^\w\s]+|\s*)netmask\s*\d+.\d+.\d+.\d+)\s*");
                Regex dnsRegex = new Regex(@"(?<dns>([^\w\s]+|\s*)dns-nameservers\s*\d+.\d+.\d+.\d+)\s*");
                Regex ipRegex = new Regex(@"\s*(?<ip>\d+.\d+.\d+.\d+)\s*");

                MatchCollection strCollection = strRegex.Matches(theReply);
                if (strCollection.Count > 0)
                {
                    MatchCollection addressCollection = addressRegex.Matches(theReply);
                    MatchCollection maskCollection = maskRegex.Matches(theReply);
                    MatchCollection gatewayCollection = gatewayRegex.Matches(theReply);
                    MatchCollection dnsCollection = dnsRegex.Matches(theReply);

                    string IP_str = addressCollection[0].Groups["address"].Value.Trim();
                    string Router_str = gatewayCollection[0].Groups["gateway"].Value.Trim();
                    string Mask_str = maskCollection[0].Groups["netmask"].Value.Trim();
                    string Server_str = dnsCollection[0].Groups["dns"].Value.Trim();
                    netInfo.IP = ipRegex.Matches(IP_str)[0].Groups["ip"].Value.Trim();
                    netInfo.Router = ipRegex.Matches(Router_str)[0].Groups["ip"].Value.Trim();
                    netInfo.Mask = ipRegex.Matches(Mask_str)[0].Groups["ip"].Value.Trim();
                    netInfo.Server = ipRegex.Matches(Server_str)[0].Groups["ip"].Value.Trim();
                }

                return netInfo;
            }
            catch (Exception ex)
            {
                LogHelper.Log(ex.ToString());
                return netInfo;
            }
        }

        public NetInfo GetJMNetInfo()
        {
            NetInfo netInfo = new NetInfo();
            try
            {
                StreamReader reader = new StreamReader(@"/etc/netplan/01-network-manager-all.yaml", Encoding.Default);
                string theReply = reader.ReadToEnd();
                reader.Close();
                Regex strRegex = new Regex(@"(?<str>([^\w\s]+|\s*)enp1s0:\s*dhcp4: no([\w\W]*))");
                Regex addressRegex = new Regex(@"([^\w\s]+|\s*)addresses:\s*[^\w\s](?<address>\d+.\d+.\d+.\d+/\d+)]\s*");
                Regex gatewayRegex = new Regex(@"(?<gateway>([^\w\s]+|\s*)via:\s*\d+.\d+.\d+.\d+)\s*");
                Regex maskReg = new Regex(@"\d+.\d+.\d+.\d+/(?<mask>\d+)\s*");
                Regex ipRegex = new Regex(@"\s*(?<ip>\d+.\d+.\d+.\d+)\s*");

                MatchCollection strCollection = strRegex.Matches(theReply);

                if (strCollection.Count > 0)
                {
                    string str_value = strCollection[0].Groups["str"].Value;
                    MatchCollection addressCollection = addressRegex.Matches(str_value);
                    MatchCollection routerCollection = gatewayRegex.Matches(str_value);
                    for (int i = 0; i < addressCollection.Count; i++)
                    {
                        string str = addressCollection[i].Groups["address"].Value.Trim();
                        string ip = ipRegex.Matches(str)[0].Groups["ip"].Value.Trim();
                        netInfo.IP = ip;
                        int mask = Convert.ToInt32(maskReg.Matches(str)[0].Groups["mask"].Value.Trim());
                        string Mask = GetMask(mask);
                        netInfo.Mask = Mask;
                    }

                    for (int i = 0; i < routerCollection.Count; i++)
                    {
                        string str = routerCollection[i].Groups["gateway"].Value.Trim();
                        string ip = ipRegex.Matches(str)[0].Groups["ip"].Value.Trim();
                        netInfo.Router = ip;
                    }
                }

                return netInfo;
            }
            catch (Exception ex)
            {
                LogHelper.Log(ex.ToString());
                return netInfo;
            }
        }

        public string GetMask(int value)
        {
            try
            {
                string str = string.Empty;
                for (int i = 0; i < value; i++)
                {
                    str += "1";
                }
                str = str.PadRight(32, '0');
                string a = Convert.ToInt32(str.Substring(0, 8), 2).ToString() + "." + Convert.ToInt32(str.Substring(8, 8), 2).ToString() + "." + Convert.ToInt32(str.Substring(16, 8), 2).ToString() + "." + Convert.ToInt32(str.Substring(24, 8), 2).ToString();
                return a;
            }
            catch
            {
                return "0.0.0.0";
            }
        }


        public bool UpdateNetInfo(NetInfo netInfo)
        {
            try
            {
                RunCommand("chmod 777 /etc/dhcpcd.conf");
                StreamReader reader = new StreamReader(@"/etc/dhcpcd.conf", Encoding.Default);
                string theReply = reader.ReadToEnd();
                reader.Close();

                Regex addressRegex = new Regex(@"(?<address>static\s*ip_address=\d+.\d+.\d+.\d+/\d+)");
                Regex routerRegex = new Regex(@"(?<router>static\s*routers=\d+.\d+.\d+.\d+)");
                Regex serverRegex = new Regex(@"(?<server>static\s*domain_name_servers=\d+.\d+.\d+.\d+)");
                Regex ipRegex = new Regex(@"=\s*(?<ip>\d+.\d+.\d+.\d+)\s*");
                Regex maskRegex = new Regex(@"=\s*(?<mask>\d+.\d+.\d+.\d+/\d+)\s*");

                MatchCollection addressCollection = addressRegex.Matches(theReply);
                MatchCollection routerCollection = routerRegex.Matches(theReply);
                MatchCollection serverCollection = serverRegex.Matches(theReply);

                string value = string.Empty;
                string[] array = netInfo.Mask.Replace(" ", "").Split('.');
                for (int i = 0; i < array.Length; i++)
                {
                    value += Convert.ToString(Convert.ToInt32(array[i]), 2);
                }
                value = value.PadRight(32, '0');

                string keyWord = "1";
                int index = 0;
                int count = 0;
                while ((index = value.IndexOf(keyWord, index)) != -1)
                {
                    count++;
                    index = index + keyWord.Length;
                }

                for (int i = 0; i < addressCollection.Count; i++)
                {
                    string str = addressCollection[i].Groups["address"].Value.Trim();
                    string oldip = maskRegex.Matches(str)[0].Groups["mask"].Value.Trim();
                    string newip = netInfo.IP + "/" + count;
                    if (oldip != newip)
                    {
                        string newstr = str.Replace(oldip, newip);
                        theReply = theReply.Replace(str, newstr);
                    }
                }

                for (int i = 0; i < routerCollection.Count; i++)
                {
                    string str = routerCollection[i].Groups["router"].Value.Trim();
                    string oldip = ipRegex.Matches(str)[0].Groups["ip"].Value.Trim();
                    if (oldip != netInfo.Router)
                    {
                        string newstr = str.Replace(oldip, netInfo.Router);
                        theReply = theReply.Replace(str, newstr);
                    }
                }

                for (int i = 0; i < serverCollection.Count; i++)
                {
                    string str = serverCollection[i].Groups["server"].Value.Trim();
                    string oldip = ipRegex.Matches(str)[0].Groups["ip"].Value.Trim();
                    if (oldip != netInfo.Server)
                    {
                        string newstr = str.Replace(oldip, netInfo.Server);
                        theReply = theReply.Replace(str, newstr);
                    }
                }

                using (FileStream fileStream = new FileStream("/etc/dhcpcd.conf", FileMode.Open, FileAccess.Write, FileShare.Write))
                {
                    fileStream.Seek(0, SeekOrigin.Begin);
                    using (StreamWriter streamWriter = new StreamWriter(fileStream))
                    {
                        streamWriter.Write(theReply);
                        fileStream.Flush();
                        streamWriter.Close();
                    }
                    fileStream.Close();
                }
                RunCommand("reboot");
                return true;
            }
            catch
            {
                return false;
            }
        }

        public bool UpdateJMNetInfo1(NetInfo netInfo)
        {
            try
            {
                StreamReader reader = new StreamReader(@"/etc/network/interfaces", Encoding.Default);
                string theReply = reader.ReadToEnd();
                reader.Close();

                Regex strRegex = new Regex(@"(?<str>([^\w\s]+|\s*)auto\s*enp1s0\s*iface\s*enp1s0\s*inet\s*static[\s\S]*)");
                MatchCollection strCollection = strRegex.Matches(theReply);
                if (strCollection.Count > 0)
                {
                    string str = strCollection[0].Groups["str"].Value.Trim();
                    theReply = theReply.Replace(str, "");
                }


                using (FileStream fileStream = new FileStream("/etc/network/interfaces", FileMode.Open, FileAccess.Write, FileShare.Write))
                {
                    fileStream.Seek(0, SeekOrigin.Begin);
                    using (StreamWriter streamWriter = new StreamWriter(fileStream))
                    {
                        streamWriter.Write(theReply);
                        streamWriter.WriteLine("auto enp1s0");
                        streamWriter.WriteLine("iface enp1s0 inet static");
                        streamWriter.WriteLine("address " + netInfo.IP);
                        streamWriter.WriteLine("netmask " + netInfo.Mask);
                        streamWriter.WriteLine("gateway " + netInfo.Router);
                        streamWriter.WriteLine("dns-nameservers " + netInfo.Server);
                        fileStream.Flush();
                        streamWriter.Close();
                    }

                    fileStream.Close();
                }
                return true;
            }
            catch
            {
                return false;
            }
        }

        public bool UpdateJMNetInfo(NetInfo netInfo)
        {
            try
            {
                //StreamReader reader = new StreamReader(@"/etc/netplan/01-network-manager-all.yaml", Encoding.Default);
                //string theReply = reader.ReadToEnd();
                //reader.Close();

                //Regex strRegex = new Regex(@"(?<str>([^\w\s]+|\s*)auto\s*enp1s0\s*iface\s*enp1s0\s*inet\s*static[\s\S]*)");
                //MatchCollection strCollection = strRegex.Matches(theReply);
                //if (strCollection.Count > 0)
                //{
                //    string str = strCollection[0].Groups["str"].Value.Trim();
                //    theReply = theReply.Replace(str, "");
                //}


                using (FileStream fileStream = new FileStream("/etc/netplan/01-network-manager-all.yaml", FileMode.Open, FileAccess.Write, FileShare.Write))
                {
                    fileStream.Seek(0, SeekOrigin.Begin);
                    fileStream.SetLength(0);
                    using (StreamWriter streamWriter = new StreamWriter(fileStream))
                    {
                        streamWriter.WriteLine("network:");
                        streamWriter.WriteLine("  version: 2");
                        streamWriter.WriteLine("  renderer: NetworkManager");
                        streamWriter.WriteLine("  ethernets:");
                        streamWriter.WriteLine("    enp2s0:");
                        streamWriter.WriteLine("      dhcp4: yes");
                        streamWriter.WriteLine("    enp1s0:");
                        streamWriter.WriteLine("      dhcp4: no");
                        streamWriter.WriteLine("      addresses: [" + netInfo.IP + "/" + netInfo.Mask + "]");
                        streamWriter.WriteLine("      routes:");
                        streamWriter.WriteLine("        - to: 0.0.0.0/0");
                        streamWriter.WriteLine("          via: " + netInfo.Router);
                        streamWriter.WriteLine("          metric: 150");
                        streamWriter.WriteLine("      optional: true");
                        fileStream.Flush();
                        streamWriter.Close();
                    }

                    fileStream.Close();
                }
                RunCommand("netplan apply");
                return true;
            }
            catch
            {
                return false;
            }
        }

        public bool CalibrationTime(string time)
        {
            try
            {
                RunCommand("date -s \"" + time + "\"");
                return true;
            }
            catch
            {
                return false;
            }
        }

        public string GetNtpIp()
        {
            try
            {
                StreamReader reader = new StreamReader(@"/etc/ntp.conf", Encoding.Default);
                string theReply = reader.ReadToEnd();
                reader.Close();
                Regex addressRegex = new Regex(@"server\s*(?<ip>\d+.\d+.\d+.\d+)\s*prefer");

                MatchCollection addressCollection = addressRegex.Matches(theReply);
                string str = addressCollection[0].Groups["ip"].Value.Trim();

                return str;
            }
            catch
            {
                return "";
            }
        }
    }
}
